/**
* Copyright (C) 2018-2020
* All rights reserved, Designed By www.gzchengguo.cn
* 注意：
* 本软件为www.gzchengguo.cn开发研制，未经购买不得商用
* 购买后可获得全部源代码（禁止转卖、分享、上传到码云、github等开源平台）
* 一经发现盗用、分享等行为，将追究法律责任，后果自负
*/
package link.chengguo.orangemall.modules.order.rest;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import link.chengguo.orangemall.annotation.AnonymousAccess;
import link.chengguo.orangemall.dozer.service.IGenerator;
import link.chengguo.orangemall.enums.OrderInfoEnum;
import link.chengguo.orangemall.enums.ShopCommonEnum;
import link.chengguo.orangemall.exception.BadRequestException;
import link.chengguo.orangemall.logging.aop.log.Log;
import link.chengguo.orangemall.modules.aop.ForbidSubmit;
import link.chengguo.orangemall.modules.order.domain.OrangeStoreOrder;
import link.chengguo.orangemall.modules.order.param.ExpressParam;
import link.chengguo.orangemall.modules.order.service.OrangeStoreOrderService;
import link.chengguo.orangemall.modules.order.service.OrangeStoreOrderStatusService;
import link.chengguo.orangemall.modules.order.service.dto.OrderCountDto;
import link.chengguo.orangemall.modules.order.service.dto.OrangeStoreOrderDto;
import link.chengguo.orangemall.modules.order.service.dto.OrangeStoreOrderQueryCriteria;
import link.chengguo.orangemall.tools.express.ExpressService;
import link.chengguo.orangemall.tools.express.config.ExpressAutoConfiguration;
import link.chengguo.orangemall.tools.express.dao.ExpressInfo;
import com.alibaba.fastjson.JSONArray;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.util.List;
import java.util.Map;

/**
 * @author chengguo
 * @date 2019-10-14
 */
@Api(tags = "商城:订单管理")
@RestController
@RequestMapping("api")
@Slf4j
@SuppressWarnings("unchecked")
public class StoreOrderController {

    @Value("${orangemall.apiUrl}")
    private String apiUrl;

    private final IGenerator generator;
    private final OrangeStoreOrderService orangeStoreOrderService;
    private final OrangeStoreOrderStatusService orangeStoreOrderStatusService;


    public StoreOrderController(IGenerator generator, OrangeStoreOrderService orangeStoreOrderService,
                                OrangeStoreOrderStatusService orangeStoreOrderStatusService) {
        this.generator = generator;
        this.orangeStoreOrderService = orangeStoreOrderService;
        this.orangeStoreOrderStatusService = orangeStoreOrderStatusService;
    }

    /**@Valid
     * 根据商品分类统计订单占比
     */
    @GetMapping("/orangeStoreOrder/orderCount")
    @ApiOperation(value = "根据商品分类统计订单占比",notes = "根据商品分类统计订单占比",response = ExpressParam.class)
    public ResponseEntity orderCount(){
        OrderCountDto orderCountDto  = orangeStoreOrderService.getOrderCount();
        return new ResponseEntity<>(orderCountDto, HttpStatus.OK);
    }

    /**
     * 首页订单/用户等统计
     * @return OrderTimeDataDto
     */
    @GetMapping(value = "/data/count")
    @AnonymousAccess
    public ResponseEntity getCount() {
        return new ResponseEntity<>(orangeStoreOrderService.getOrderTimeData(), HttpStatus.OK);
    }

    /**
     * 返回本月订单金额与数量chart
     * @return map
     */
    @GetMapping(value = "/data/chart")
    @AnonymousAccess
    public ResponseEntity getChart() {
        return new ResponseEntity<>(orangeStoreOrderService.chartCount(), HttpStatus.OK);
    }


    @ApiOperation(value = "查询订单")
    @GetMapping(value = "/orangeStoreOrder")
    @PreAuthorize("hasAnyRole('admin','ORANGESTOREORDER_ALL','ORANGESTOREORDER_SELECT','ORANGEEXPRESS_SELECT')")
    public ResponseEntity getOrangeStoreOrders(OrangeStoreOrderQueryCriteria criteria,
                                           Pageable pageable,
                                           @RequestParam(name = "orderStatus") String orderStatus,
                                           @RequestParam(name = "orderType") String orderType) {

        OrangeStoreOrderQueryCriteria newCriteria = this.handleQuery(criteria,orderStatus,orderType);

        return new ResponseEntity<>(orangeStoreOrderService.queryAll(newCriteria, pageable), HttpStatus.OK);
    }


    @ApiOperation(value = "发货")
    @PutMapping(value = "/orangeStoreOrder")
    @PreAuthorize("hasAnyRole('admin','ORANGESTOREORDER_ALL','ORANGESTOREORDER_EDIT')")
    public ResponseEntity update(@Validated @RequestBody OrangeStoreOrder resources) {
        if (StrUtil.isBlank(resources.getDeliveryName())) {
            throw new BadRequestException("请选择快递公司");
        }
        if (StrUtil.isBlank(resources.getDeliveryId())) {
            throw new BadRequestException("快递单号不能为空");
        }

        orangeStoreOrderService.orderDelivery(resources.getOrderId(),resources.getDeliveryId(),
                resources.getDeliveryName(),resources.getDeliveryType());
        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }

    @ApiOperation(value = "订单核销")
    @PutMapping(value = "/orangeStoreOrder/check")
    @PreAuthorize("hasAnyRole('admin','ORANGESTOREORDER_ALL','ORANGESTOREORDER_EDIT')")
    public ResponseEntity check(@Validated @RequestBody OrangeStoreOrder resources) {
        if (StrUtil.isBlank(resources.getVerifyCode())) {
            throw new BadRequestException("核销码不能为空");
        }
        OrangeStoreOrderDto storeOrderDTO = generator.convert(orangeStoreOrderService.getById(resources.getId()), OrangeStoreOrderDto.class);
        if(!resources.getVerifyCode().equals(storeOrderDTO.getVerifyCode())){
            throw new BadRequestException("核销码不对");
        }
        if(OrderInfoEnum.PAY_STATUS_0.getValue().equals(storeOrderDTO.getPaid())){
            throw new BadRequestException("订单未支付");
        }

        orangeStoreOrderService.verificOrder(resources.getVerifyCode(),
                OrderInfoEnum.CONFIRM_STATUS_1.getValue(),null);

        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }


    @ApiOperation(value = "退款")
    @PostMapping(value = "/orangeStoreOrder/refund")
    @PreAuthorize("hasAnyRole('admin','ORANGESTOREORDER_ALL','ORANGESTOREORDER_EDIT')")
    public ResponseEntity refund(@Validated @RequestBody OrangeStoreOrder resources) {
        orangeStoreOrderService.orderRefund(resources.getOrderId(),resources.getPayPrice(),
                ShopCommonEnum.AGREE_1.getValue());
        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }


    @ForbidSubmit
    @Log("删除")
    @ApiOperation(value = "删除")
    @DeleteMapping(value = "/orangeStoreOrder/{id}")
    @PreAuthorize("hasAnyRole('admin','ORANGESTOREORDER_ALL','ORANGESTOREORDER_DELETE')")
    public ResponseEntity delete(@PathVariable Integer id) {
        orangeStoreOrderService.removeById(id);
        return new ResponseEntity(HttpStatus.OK);
    }


    @Log("修改订单")
    @ApiOperation(value = "修改订单")
    @PostMapping(value = "/orangeStoreOrder/edit")
    @PreAuthorize("hasAnyRole('admin','ORANGESTOREORDER_ALL','ORANGESTOREORDER_EDIT')")
    public ResponseEntity editOrder(@RequestBody OrangeStoreOrder resources) {
        if (ObjectUtil.isNull(resources.getPayPrice())) {
            throw new BadRequestException("请输入支付金额");
        }
        if (resources.getPayPrice().doubleValue() < 0) {
            throw new BadRequestException("金额不能低于0");
        }
        OrangeStoreOrderDto storeOrder = generator.convert(orangeStoreOrderService.getById(resources.getId()), OrangeStoreOrderDto.class);
        //判断金额是否有变动,生成一个额外订单号去支付
        int res = NumberUtil.compare(storeOrder.getPayPrice().doubleValue(), resources.getPayPrice().doubleValue());
        if (res != 0) {
            String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
            resources.setExtendOrderId(orderSn);
        }

        orangeStoreOrderService.saveOrUpdate(resources);

        orangeStoreOrderStatusService.create(resources.getId(),"order_edit",
                "修改订单价格为：" + resources.getPayPrice());
        return new ResponseEntity(HttpStatus.OK);
    }


    @Log("修改订单备注")
    @ApiOperation(value = "修改订单备注")
    @PostMapping(value = "/orangeStoreOrder/remark")
    @PreAuthorize("hasAnyRole('admin','ORANGESTOREORDER_ALL','ORANGESTOREORDER_EDIT')")
    public ResponseEntity editOrderRemark(@RequestBody OrangeStoreOrder resources) {
        if (StrUtil.isBlank(resources.getRemark())) {
            throw new BadRequestException("请输入备注");
        }
        orangeStoreOrderService.saveOrUpdate(resources);
        return new ResponseEntity(HttpStatus.OK);
    }


    /**
     * 快递查询
     */
    @PostMapping("/orangeStoreOrder/express")
    @ApiOperation(value = "获取物流信息",notes = "获取物流信息",response = ExpressParam.class)
    public ResponseEntity express( @RequestBody ExpressParam expressInfoDo){
        ExpressService expressService = ExpressAutoConfiguration.expressService();
        ExpressInfo expressInfo = expressService.getExpressInfo(expressInfoDo.getOrderCode(),
                expressInfoDo.getShipperCode(), expressInfoDo.getLogisticCode());
        if(!expressInfo.isSuccess()) {
            throw new BadRequestException(expressInfo.getReason());
        }
        return new ResponseEntity<>(expressInfo, HttpStatus.OK);
    }

    @Log("导出数据")
    @ApiOperation("导出数据")
    @GetMapping(value = "/orangeStoreOrder/download")
    @PreAuthorize("hasAnyRole('admin','ORANGESTOREORDER_SELECT')")
    public void download(HttpServletResponse response,
                         OrangeStoreOrderQueryCriteria criteria,
                         Pageable pageable,
                         @RequestParam(name = "orderStatus") String orderStatus,
                         @RequestParam(name = "orderType") String orderType,
                         @RequestParam(name = "listContent") String listContent) throws IOException, ParseException {
        List<OrangeStoreOrderDto> list;
        if(StringUtils.isEmpty(listContent)){
            list =  (List)getOrangeStoreList(criteria, pageable, orderStatus, orderType).get("content");
        }else {
            List<String> idList = JSONArray.parseArray(listContent).toJavaList(String.class);
            list = (List) orangeStoreOrderService.queryAll(idList).get("content");
        }
        orangeStoreOrderService.download(list, response);
    }

    /**
     * 下载数据
     * @param criteria criteria
     * @param pageable pageable
     * @param orderStatus orderStatus
     * @param orderType orderType
     * @return Map
     */
    private Map<String,Object> getOrangeStoreList(OrangeStoreOrderQueryCriteria criteria,
                                              Pageable pageable,
                                              String orderStatus,
                                              String orderType){

        OrangeStoreOrderQueryCriteria newCriteria = this.handleQuery(criteria,orderStatus,orderType);
        return orangeStoreOrderService.queryAll(newCriteria, pageable);
    }



    /**
     * 处理订单查询
     * @param criteria OrangeStoreOrderQueryCriteria
     * @param orderStatus 订单状态
     * @param orderType 订单类型
     * @return OrangeStoreOrderQueryCriteria
     */
    private OrangeStoreOrderQueryCriteria handleQuery(OrangeStoreOrderQueryCriteria criteria, String orderStatus,
                                                      String orderType){


        criteria.setShippingType(OrderInfoEnum.SHIPPIING_TYPE_1.getValue());//默认查询所有快递订单
        //订单状态查询
        if (StrUtil.isNotEmpty(orderStatus)) {
            switch (orderStatus) {
                case "0":
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_0.getValue());
                    criteria.setStatus(OrderInfoEnum.STATUS_0.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue());
                    break;
                case "1":
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setStatus(OrderInfoEnum.STATUS_0.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue());
                    break;
                case "2":
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setStatus(OrderInfoEnum.STATUS_1.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue());
                    break;
                case "3":
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setStatus(OrderInfoEnum.STATUS_2.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue());
                    break;
                case "4":
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setStatus(OrderInfoEnum.STATUS_3.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_0.getValue());
                    break;
                case "-1":
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_1.getValue());
                    break;
                case "-2":
                    criteria.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
                    criteria.setRefundStatus(OrderInfoEnum.REFUND_STATUS_2.getValue());
                    break;
            }
        }
        //订单类型查询
        if (StrUtil.isNotEmpty(orderType)) {
            switch (orderType) {
                case "1":
                    criteria.setBargainId(0);
                    criteria.setCombinationId(0);
                    criteria.setSeckillId(0);
                    break;
                case "2":
                    criteria.setNewCombinationId(0);
                    break;
                case "3":
                    criteria.setNewSeckillId(0);
                    break;
                case "4":
                    criteria.setNewBargainId(0);
                    break;
                case "5":
                    criteria.setShippingType(2);
                    break;
            }
        }

        return criteria;
    }



}
